Basic Plot Befehl in Assembler

← Zurück zum Forum

Das wollte ich schon immer haben ... also muss ich es hier jetzt mal machen! Mithilfe, Optimierung und Ideen wie immer sehr willkommen.

Vorgabe: Antic D (Graphics 7), Auflösung 160x80 mit 3 (4) Farben. Die Routine soll möglichst schlank und schnell sein.

Drei Variablen: varx , vary, varcolor

AntwortZitat

Ich fange mal an: Zunächst die größte Schwierigkeit ist ja, daß man von den werten x=0 bis x=159 auf 0-39 kommen muss. Das klingt zunächst ja recht einfach, ich muss lediglich durch 4 teilen und das ist zum Glück wirklich sehr einfach. Allerdings muss man dann ja aber genau wissen, ob ich nach der Teilung Bit 1/2/3oder 4 setzen muss (in Abhängigkeit der Farbe). Man könnte jetzt eine Tabelle für alle drei Farben machen und jedem Wert von 0-159 das entsprechende Bit zuordnen - das wäre wohl der schnellste Weg, frisst aber Speicher. Das Atari Basic löst das ganz sicher anders... Meine Lösung wäre nun folgende: Ich mache 2x einen Shift nach rechts (also teile durch 4) mit LSR und addiere das Carry nach dem ersten Shift 1x zu einer Variablen und nach dem 2. Shift 2x zu einer Variablen. Die Variable hat dann nach dem 2. Shift die Werte 0,1,2 oder 3 was gleichzeitig die Position des zu setzenden Bits entspricht an der x-Position was nach dem Teilen durch 4 herauskommt. Beispiel x-Wert 53: 1. Shift: LSR 55 = 27 / Variable + Carry=1 2. Shift: LSR 27 = 13 / Variable + Carry + Carry=3

Das Bit wird also dann an der Bildschirmposition 13 geplottet, Bit 3 wird gesetzt

AntwortZitat

Also eine kleine Korrektur zum Verständnis: Mit Bit 0 meine ich das ganz Linke und mit Bit 3 das ganz Rechte... ist natürlich wenn ich es so schreibe unverständlich!

AntwortZitat

und hier die entsprechende Routine:

      org $4000 

bs1 = 250   ; Page 0 Variable     

xwert     .by 00
ywert     .by 00
varx      .by 00
posx      .by 00
wert      .by 00
color     .by 00

xconvert
      .byte 64,16,4,1   ; Farbe 1
      .byte 128,32,8,2  ; Farbe 2
      .byte 192,48,12,3 ; Farbe 3

      ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
      .byte 112,112,112
      .byte 77,96,144
:79     .byte 13
      .byte 66,96,159
      .byte 2,2,2
      .byte 65
      .word dlist
      ;------------ Textstart bei 40800 -------------------


      .proc main

      mwa #dlist 560

      ;-------------- Start Hauptprogramm ----------------------------- 


      mwa #36920 bs1    ; Start Bildschirmspeicher

      mva #77 xwert   ; Punkt (x-Wert)
      mva #33 ywert   ; Punkt (y-Wert)
      mva #4 color    ; Farbe 2 wird hier initialisiert
      mva xwert varx

@
      clc
      lda bs1
      adc #40
      sta bs1
      lda bs1+1
      adc #0
      sta bs1+1
      dec ywert
      bne @-

      clc
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
@     
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
      inc posx
@     
      clc
      lda posx
      adc color
      tax
      lda xconvert,x
      sta wert

      ldy varx
      lda (bs1),y
      eor wert
      sta (bs1),y


      jmp *

      .endp

Diese Routine plottet einen Punkt exemplarisch (77/33) bei Graphics 7 auf den Bildschirm!

AntwortZitat

... Optimierungen welcome ... 😉

Die y-Spalten habe ich für dieses Beispiel extra mit eine (+40) Schleife berechnen lassen. Schneller ginge das natürlich mit einer Tabelle - und im normalen Spiel würde ich das auch entsprechend mit einer Tabelle machen!

AntwortZitat

Hallo!


  ldy varx
  lda (bs1),y
  eor wert
  sta (bs1),y

Würde immer nur Bits hinzuaddieren, aber nicht mehr löschen. Man könnte somit nicht die Farbe ändern oder gar auf 0 setzen. Man sollte vorm "eor" noch ein "and" setzen mit einer Maske, der die Bits des Pixels löscht.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Hallo!

Hier einmal eine angepasste Version, wo ich die Maske nutze. Das erste Pixel wird mit dem 4. Pixel überschrieben:

      org $4000 

bs1 = 250   ; Page 0 Variable     

xwert     .by 00
ywert     .by 00
varx      .by 00
posx      .by 00
wert      .by 00
color     .by 00

xconvert
      .byte 64,16,4,1   ; Farbe 1
      .byte 128,32,8,2  ; Farbe 2
      .byte 192,48,12,3 ; Farbe 3

      ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
      .byte 112,112,112
      .byte 77,96,144
:79     .byte 13
      .byte 66,96,159
      .byte 2,2,2
      .byte 65
      .word dlist
      ;------------ Textstart bei 40800 -------------------


      .proc main

      mwa #dlist 560

      ;-------------- Start Hauptprogramm ----------------------------- 


      mva #77 xwert   ; Punkt (x-Wert)
      mva #33 ywert   ; Punkt (y-Wert)
      mva #3 color    ; Farbe 3 
      jsr setpixel

      mva #76 xwert   ; Punkt (x-Wert)
      mva #33 ywert   ; Punkt (y-Wert)
      mva #2 color    ; Farbe 2 
      jsr setpixel

      mva #76 xwert   ; Punkt (x-Wert)
      mva #32 ywert   ; Punkt (y-Wert)
      mva #1 color    ; Farbe 1 
      jsr setpixel

      mva #77 xwert   ; Punkt (x-Wert)
      mva #33 ywert   ; Punkt (y-Wert)
      mva #1 color    ; Farbe 1 --> Pixles mit Farbe 3 wird überschrieben
      jsr setpixel

      jmp *

      .endp

      .proc setpixel

      mwa #36920 bs1    ; Start Bildschirmspeicher
@
      clc
      lda bs1
      adc #40
      sta bs1
      lda bs1+1
      adc #0
      sta bs1+1
      dec ywert
      bne @-

      clc
      lda xwert
      and #%00000011    ; untern 2 Bits retten
      tax
      lda xwert
      lsr
      lsr     ; durch 4 teilen
      tay

      lda (bs1),y
      and COLOR0,X

      lda color
      beq setpixel    ; Farbe 0 = löschen = fertig
      cmp #1
      bne @+      ; nicht Farbe 1 dann weiter
      lda COLOR1,X
      jmp setpixel
@     cmp #2
      bne @+      ; nicht Farbe 2 dann weiter
      lda COLOR2,X
      jmp setpixel
@     lda COLOR3,X      

setpixel    eor (bs1),y
      sta (bs1),y


      rts

COLOR0      dta $3F,$CF,$F3,$FC
COLOR1      dta $40,$10,$04,$01     
COLOR2      dta $80,$20,$08,$02     
COLOR3      dta $C0,$30,$0C,$03     
      .endp
      run main

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

meine Lösung wäre jetzt diese:

      org $4000 

bs1 = 250   ; Page 0 Variable     

xwert     .by 00
ywert     .by 00
varx      .by 00
posx      .by 00
wert      .by 00
color     .by 00


xconvert
      .byte 64,16,4,1   ; Farbe 1
      .byte 128,32,8,2  ; Farbe 2
      .byte 192,48,12,3 ; Farbe 3

      ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
      .byte 112,112,112
      .byte 77,96,144
:79     .byte 13
      .byte 66,96,159
      .byte 2,2,2
      .byte 65
      .word dlist
      ;------------ Textstart bei 40800 -------------------


      .proc main

      mwa #dlist 560

      ;-------------- Start Hauptprogramm ----------------------------- 


      mwa #36920 bs1    ; Start Bildschirmspeicher

      mva #1 xwert    ; Punkt (x-Wert)
      mva #1 ywert    ; Punkt (y-Wert)
      mva #4 color    ; Farbe 2 wird hier initialisiert
      mva xwert varx

@
      clc
      lda bs1
      adc #40
      sta bs1
      lda bs1+1
      adc #0
      sta bs1+1
      dec ywert
      bne @-

      clc
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
@     
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
      inc posx
@     
      clc
      lda posx
      adc color
      tax
      lda xconvert,x
      sta wert

      ldy varx
      lda (bs1),y

      ldx posx
      cpx #0
      bne @+
      rol
      clc
      rol
      clc
      ror
      ror
      jmp print
@     cpx #1
      bne @+
      rol
      rol
      rol
      clc
      rol
      clc
      ror
      ror
      ror
      ror
      jmp print
@
      cpx #2
      bne @+
      ror
      ror
      ror
      clc
      ror
      clc
      rol
      rol
      rol
      rol
      jmp print
@
      ror
      clc
      ror
      clc
      rol
      rol
print     
      eor wert
      sta (bs1),y


      jmp *

      .endp

... etwas mehr Code vielleicht, aber vielleicht schneller, da die ROL/ROR jeweils nur 2 Taktzyklen brauchen - habe es aber auch nicht ausgerechnet, Jankos Lösung ist in jedem Fall eleganter... 😉

AntwortZitat

das hat mir jetzt keine Ruhe gelassen... hier der Code mit Maske, ohne die Shifts...

      org $4000 

bs1 = 250   ; Page 0 Variable     

xwert     .by 00
ywert     .by 00
varx      .by 00
posx      .by 00
wert      .by 00
color     .by 00

maske     
      .byte 63,207,243,252


xconvert
      .byte 64,16,4,1   ; Farbe 1
      .byte 128,32,8,2  ; Farbe 2
      .byte 192,48,12,3 ; Farbe 3

      ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
      .byte 112,112,112
      .byte 77,96,144
:79     .byte 13
      .byte 66,96,159
      .byte 2,2,2
      .byte 65
      .word dlist
      ;------------ Textstart bei 40800 -------------------


      .proc main

      mwa #dlist 560

      ;-------------- Start Hauptprogramm ----------------------------- 

      mwa #36920 bs1


      mva #0 xwert    ; Punkt (x-Wert)
      mva #1 ywert    ; Punkt (y-Wert)
      mva #0 color    ; Farbe 1
      ;mva #4 color   ; Farbe 2
      ;mva #8 color   ; Farbe 3
      mva xwert varx

@
      clc
      lda bs1
      adc #40
      sta bs1
      lda bs1+1
      adc #0
      sta bs1+1
      dec ywert
      bne @-

      clc
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
@     
      lda varx
      lsr
      sta varx
      bcc @+
      inc posx
      inc posx
@     
      clc
      lda posx
      adc color
      tax
      lda xconvert,x
      sta wert
      ldy varx
      lda (bs1),y
      ldx posx
      and maske,x
      eor wert
      sta (bs1),y


      jmp *


      .endp


      run main
AntwortZitat

Ich hab da zwar nicht viel verstanden, aber ohne die ROL/ROR sieht das übersichtlicher aus. Wenn man das nur ein ROL vergisst, RORtiert das ganze Programm 😁 Obs schneller ist, müsste man testen. Aber da sieht man mal wieder was für einen Aufwand man für ein einzelnes Pünktchen treiben kann. Gruß und viel Spass beim weiter optimieren. Ist sehr spannend 😀 Wolfgang

AntwortZitat